home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / MRUTC.LZH / EDITOR.C < prev    next >
Text File  |  1987-12-29  |  15KB  |  729 lines

  1. /* ----------------------- editor.c ---------------------- */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <mem.h>
  6. #include <conio.h>
  7. #include <alloc.h>
  8. #include "twindow.h"
  9. #include "keys.h"
  10.  
  11. #define TRUE 1
  12. #define FALSE 0
  13. #define TAB 4
  14. #define NEXTTAB (TAB-(x%TAB))
  15. #define LASTTAB (((wwd-1)/TAB)*TAB)
  16. #define PREVTAB (((x-1)%TAB)+1)
  17. #define curr(x,y) (bfptr+(y)*wwd+(x))
  18. #define lineno(y) ((int)(bfptr-topptr)/wwd+(y))
  19.  
  20. extern int VSG;
  21. int last_x, last_y;
  22. static int wht;
  23. static int wwd;
  24. static int wsz;
  25. static char *topptr;
  26. static char *bfptr;
  27. static char *lstptr;
  28. static int lines;
  29. static char *endptr;
  30. static int blkbeg;
  31. static int blkend;
  32. static int inserting;
  33. static WINDOW *wnd;
  34. static int do_display_text = 1;
  35. /*page*/
  36. /* ---------- local function prototypes ----------- */
  37. void erase_buffer(int *x, int *y);
  38. int lastword(int x, int y);
  39. void last_char(int *x, int *y);
  40. void test_para(int x, int y);
  41. int trailing_spaces(int y);
  42. int first_wordlen(int y);
  43. void paraform(int x, int y);
  44. int blankline(int line);
  45. void delete_word(int x, int y);
  46. void delete_line(int y);
  47. void delete_block(void);
  48. void copy_block(int y);
  49. void move_block(int y);
  50. void mvblock(int y, int moving);
  51. void findlast(void);
  52. void find_end(int *x, int *y);
  53. void carrtn(int *x, int *y, int insert);
  54. void backspace(int *x, int *y);
  55. void fore_word(int *x, int *y, char *bf);
  56. int spaceup(int *x, int *y, char **bf);
  57. void back_word(int *x, int *y, char *bf);
  58. int spacedn(int *x, int *y, char **bf);
  59. void forward(int *x, int *y);
  60. int downward(int *y);
  61. void upward(int *y);
  62. void display_text(void);
  63. void disp_line(int y);
  64. void insert_line(void);
  65. /*page*/
  66. /* ----- Process text entry for a window. ---- */
  67. void text_editor(WINDOW *wnd1, char *bf, unsigned bsize)
  68. {
  69.     char *b, *buff;
  70.     int depart = FALSE, i, c;
  71.     int x, y, svx, svlw, tx, tabctr = 0;
  72.  
  73.     wnd = wnd1;
  74.     wht = HEIGHT-2;
  75.     wwd = WIDTH-2;
  76.     wsz = wwd * wht;
  77.     topptr = bfptr = bf;
  78.     lines = bsize / wwd;
  79.     endptr = bf + wwd * lines;
  80.     blkbeg = 0;
  81.     blkend = 0;
  82.     inserting = FALSE;
  83.     x = 0;
  84.     y = 0;
  85.     display_text();
  86.     /* --------- read in text from the keyboard ---------- */
  87.     findlast();
  88.     while (TRUE)    {
  89.         last_x = COL + 1 + x;
  90.         last_y = ROW + 1 + y;
  91.         cursor(last_x, last_y);
  92.         buff = curr(x, y);
  93.         if (tabctr)    {
  94.             --tabctr;
  95.             c = ' ';
  96.         }
  97.         else    {
  98.             c = get_char();
  99.             clear_message();
  100.         }
  101.         switch (c)    {
  102.             case '\r':    carrtn(&x, &y, inserting);
  103.                         break;
  104.             case DN:    downward(&y);
  105.                         break;
  106.             case PGUP:    y = 0;
  107.                         for (i = 0; i < wht; i++)
  108.                             upward(&y);
  109.                         break;
  110.             case PGDN:    y = HEIGHT - 2;
  111.                         for (i = 0; i < wht; i++)
  112.                             downward(&y);
  113.                         y = 0;
  114.                         break;
  115.             case '\t':    if (x + NEXTTAB < wwd)    {
  116.                             if (inserting)
  117.                                 tabctr = NEXTTAB;
  118.                             else
  119.                                 x += NEXTTAB;
  120.                         }
  121.                         else
  122.                             carrtn(&x, &y, inserting);
  123.                         break;
  124.             case SHIFT_HT:
  125.                         if (x < TAB)    {
  126.                             upward(&y);
  127.                             x = LASTTAB;
  128.                         }
  129.                         else
  130.                             x -= PREVTAB;
  131.                         break;
  132.             case CTRL_FWD:
  133.                         fore_word(&x, &y, buff);
  134.                         break;
  135.             case CTRL_BS:
  136.                         back_word(&x, &y, buff);
  137.                         break;
  138.             case CTRL_B:
  139.                         y = wht - 1;
  140.                         break;
  141.             case CTRL_T:
  142.                         y = 0;
  143.                         break;
  144.             case CTRL_HOME:
  145.                         x = y = 0;
  146.                         bfptr = topptr;
  147.                         display_text();
  148.                         break;
  149.             case HOME:    x = 0;
  150.                         break;
  151.             case CTRL_END:
  152.                         find_end(&x, &y);
  153.                         display_text();
  154.                         break;
  155.             case END:    last_char(&x, &y);
  156.                         break;
  157.             case UP:    upward(&y);
  158.                         break;
  159.             case F2:
  160.             case ESC:    depart = TRUE;
  161.                         break;
  162.             case '\b':
  163.             case BS:    if (curr(x, y) == topptr)
  164.                             break;
  165.                         backspace(&x, &y);
  166.                         if (x == wwd - 1)
  167.                             last_char(&x, &y);
  168.                         if (c == BS)
  169.                             break;
  170.                         buff = curr(x, y);
  171.             case DEL:    movmem(buff+1, buff, wwd-1-x);
  172.                         *(buff+wwd-1-x) = ' ';
  173.                         disp_line(y);
  174.                         test_para(x+1, y);
  175.                         break;
  176.             case ALT_D:    delete_line(y);
  177.                         break;
  178.             case CTRL_D:delete_word(x, y);
  179.                         test_para(x, y);
  180.                         break;
  181.             case INS:    inserting ^= TRUE;
  182.                         insert_line();
  183.                         break;
  184.             case F3:    erase_buffer(&x, &y);
  185.                         break;
  186.             case F4:    paraform(0, y);
  187.                         break;
  188.             case F5:    blkbeg = lineno(y) + 1;
  189.                         if (blkbeg > blkend)
  190.                             blkend = lines;
  191.                         display_text();
  192.                         break;
  193.             case F6:    blkend = lineno(y) + 1;
  194.                         if (blkend < blkbeg)
  195.                             blkbeg = 1;
  196.                         display_text();
  197.                         break;
  198.             case F7:    move_block(y);
  199.                         break;
  200.             case F8:    copy_block(y);
  201.                         break;
  202.             case F9:    delete_block();
  203.                         break;
  204.             case F10:    blkbeg = blkend = 0;
  205.                         display_text();
  206.                         break;
  207.             case FWD:    forward(&x, &y);
  208.                         break;
  209.             default:    if (!isprint(c))
  210.                             break;
  211.                         if (curr(x, y) == endptr-1 ||
  212.                            (lineno(y)+1 >= lines && inserting
  213.                                 && *curr(wwd-2, y) != ' '))    {
  214.                             error_message(" End of Buffer ");
  215.                             break;
  216.                         }
  217.                         if (inserting)    {
  218.                             buff = curr(x, y);
  219.                             movmem(buff, buff + 1, wwd-1-x);
  220.                         }
  221.                         buff = curr(x, y);
  222.                         if (buff < endptr)    {
  223.                             if (buff >= lstptr)
  224.                                 lstptr = buff + 1;
  225.                             *buff = c;
  226.                             disp_line(y);
  227.                         }
  228.                         buff = curr(wwd-1, y);
  229.                         if (endptr && *buff != ' ')    {
  230.                             for (b = buff+1; b < endptr; b++)
  231.                                 if (*b==' ' && *(b + 1)==' ')
  232.                                     break;
  233.                             movmem(buff+1, buff+2, b-buff-1);
  234.                             *(buff+1) = ' ';
  235.                             svx = x;
  236.                             svlw = lastword(x, y);
  237.                             x = wwd-1;
  238.                             if (*(buff-1) != ' ')
  239.                                 back_word(&x, &y, buff);
  240.                             tx = x;
  241.                             carrtn(&x, &y, TRUE);
  242.                             if (svlw)
  243.                                 x = svx-tx;
  244.                             else    {
  245.                                 x = svx;
  246.                                 --y;
  247.                             }
  248.                         }
  249.                         forward(&x, &y);
  250.                         break;
  251.         }
  252.         if (depart)
  253.             break;
  254.     }
  255.     inserting = FALSE;
  256.     insert_line();
  257. }
  258. /*page*/
  259. /* -------- erase the buffer --------------- */
  260. static void erase_buffer(int *x, int *y)
  261. {
  262.     int c = 0;
  263.     WINDOW *sur;
  264.  
  265.     sur = establish_window(28, 11, 4, 24);
  266.     set_colors(sur, ALL, RED, YELLOW, BRIGHT);
  267.     display_window(sur);
  268.     wprintf(sur, " Erase text window\n Are you sure? (y/n)");
  269.     while (c != 'y' && c != 'n')    {
  270.         c = get_char();
  271.         c = tolower(c);
  272.         if (c == 'y')    {
  273.             lstptr = bfptr = topptr;
  274.             *x = *y = 0;
  275.             setmem(bfptr, lines * wwd, ' ');
  276.             blkbeg = blkend = 0;
  277.             display_text();
  278.         }
  279.     }
  280.     delete_window(sur);
  281. }
  282.  
  283. /* ----- see if a word is the last word on the line ------ */
  284. static int lastword(int x, int y)
  285. {
  286.     char *bf = curr(x, y);
  287.  
  288.     while (x++ < wwd-1)
  289.         if (*bf++ == ' ')
  290.             return 0;
  291.     return 1;
  292. }
  293. /*page*/
  294. /* --- go to last displayable character on the line --- */
  295. static void last_char(int *x, int *y)
  296. {
  297.     char *bf;
  298.  
  299.     *x = wwd-1;
  300.     bf = curr(0, *y);
  301.     while (*x && *(bf + *x) == ' ')
  302.         --(*x);
  303.     if (*x && *x < wwd - 1)
  304.         (*x)++;
  305. }
  306.  
  307. /* ----- test to see if paragraph should be reformed ----- */
  308. static void test_para(int x, int y)
  309. {
  310.     int ts, fw;
  311.  
  312.     if (!scroll_lock() && y < lines)    {
  313.         ts = trailing_spaces(y);
  314.         fw = first_wordlen(y+1);
  315.         if (fw && ts > fw)
  316.             paraform(x, y);
  317.     }
  318. }
  319.  
  320. /* ---- count the trailing spaces on a line ----- */
  321. static int trailing_spaces(int y)
  322. {
  323.     int x = wwd-1, ct = 0;
  324.     char *bf = curr(0, y);
  325.  
  326.     while (x >= 0)    {
  327.         if (*(bf + x) != ' ')
  328.             break;
  329.         --x;
  330.         ct++;
  331.     }
  332.     return ct;
  333. }
  334. /* ----- count the length of the first word on a line --- */
  335. static int first_wordlen(int y)
  336. {
  337.     int ct = 0, x = 0;
  338.     char *bf = curr(0, y);
  339.  
  340.     while (x < wwd-1 && *(bf+x) == ' ')
  341.         x++;
  342.     while (x+ct < wwd-1 && *(bf+x+ct) != ' ')
  343.         ct++;
  344.     return ct;
  345. }
  346.  
  347.  
  348. /* ------------ form a paragraph -------------- */
  349. static void paraform(int x, int y)
  350. {
  351.     char *cp1, *cp2, *cpend, *svcp;
  352.     int x1;
  353.  
  354.     if (blankline(lineno(y)+1))
  355.         return;
  356.     if (!blkbeg)    {
  357.         blkbeg = blkend = lineno(y)+1;
  358.         blkend++;
  359.         while (blkend < lines)    {
  360.             if (blankline(blkend))
  361.                 break;
  362.             blkend++;
  363.         }
  364.         --blkend;
  365.     }
  366.     if (lineno(y) != blkbeg-1)
  367.         x = 0;
  368.     x1 = x;
  369.     cp1 = cp2 = topptr + (blkbeg - 1) * wwd + x;
  370.     cpend = topptr + blkend * wwd;
  371.     while (cp2 < cpend)    {
  372.         while (*cp2 == ' ' && cp2 < cpend)
  373.             cp2++;
  374.         if (cp2 == cpend)
  375.             break;
  376.         /* at a word */
  377.         while (*cp2 != ' ' && cp2 < cpend)    {
  378.             if (x1 >= wwd - 1)    {
  379.                 /* wrap the word */
  380.                 svcp = cp1 + (wwd - x1);
  381.                 while (*--cp1 != ' ')    {
  382.                     *cp1 = ' ';
  383.                     --cp2;
  384.                 }
  385.                 x1 = 0;
  386.                 blkbeg++;
  387.                 cp1 = svcp;
  388.             }
  389.             *cp1++ = *cp2++;
  390.             x1++;
  391.         }
  392.         if (cp2 < cpend)    {
  393.             *cp1++ = ' ';
  394.             x1++;
  395.         }
  396.     }
  397.     while (cp1 < cpend)
  398.         *cp1++ = ' ';
  399.      blkbeg++;
  400.      if (blkbeg <= blkend)
  401.         delete_block();
  402.     blkbeg = blkend = 0;
  403.     display_text();
  404.     findlast();
  405. }
  406. /*page*/
  407. /* ------- test for a blank line ---------- */
  408. static int blankline(int line)
  409. {
  410.     char *cp;
  411.     int x;
  412.  
  413.     cp = topptr + (line-1) * wwd;
  414.     for (x = 0; x < wwd; x++)
  415.         if (*(cp + x) != ' ')
  416.             break;
  417.     return (x == wwd);
  418. }
  419.  
  420. /* ------------- delete a word -------------- */
  421. static void delete_word(int x, int y)
  422. {
  423.     int wct = 0;
  424.     char *cp1, *cp2;
  425.  
  426.     cp1 = cp2 = curr(x, y);
  427.     if (*cp2 == ' ')
  428.         while (*cp2 == ' ' && x + wct < wwd)    {
  429.             wct++;
  430.             cp2++;
  431.         }
  432.     else    {
  433.         while (*cp2 != ' ' && x + wct < wwd)    {
  434.             wct++;
  435.             cp2++;
  436.         }
  437.         while (*cp2 == ' ' && x + wct < wwd)    {
  438.             wct++;
  439.             cp2++;
  440.         }
  441.     }
  442.     movmem(cp2, cp1, wwd - x - wct);
  443.     setmem(cp1 + wwd - x - wct, wct, ' ');
  444.     display_text();
  445.     findlast();
  446. }
  447. /* ----------- delete a line --------------- */
  448. static void delete_line(int y)
  449. {
  450.     char *cp1, *cp2;
  451.     int len;
  452.  
  453.     cp1 = bfptr + y * wwd;
  454.     cp2 = cp1 + wwd;
  455.     if (cp1 < lstptr)    {
  456.         len = endptr - cp2;
  457.         movmem(cp2, cp1, len);
  458.         lstptr -= wwd;
  459.         setmem(endptr - wwd, wwd, ' ');
  460.         display_text();
  461.     }
  462. }
  463.  
  464. /* ----------- delete a block ------------- */
  465. static void delete_block()
  466. {
  467.     char *cp1, *cp2;
  468.     int len;
  469.  
  470.     if (!blkbeg || !blkend)    {
  471.         putchar(BELL);
  472.         return;
  473.     }
  474.     cp1 = topptr + blkend * wwd;
  475.     cp2 = topptr + (blkbeg - 1) * wwd;
  476.     len = endptr - cp1;
  477.     movmem(cp1, cp2, len);
  478.     setmem(cp2 + len, endptr - (cp2 + len), ' ');
  479.     blkbeg = blkend = 0;
  480.     lstptr -= (cp1 - cp2);
  481.     display_text();
  482. }
  483. /*page*/
  484. /* ------- move and copy text blocks -------- */
  485. static void mvblock(int y, int moving)
  486. {
  487.     char *cp1, *cp2, *hd;
  488.     int len;
  489.     if (!blkbeg || !blkend)    {
  490.         putchar(BELL);
  491.         return;
  492.     }
  493.     if (lineno(y) >= blkbeg-1 && lineno(y) <= blkend-1)    {
  494.         error_message("Can't move/copy a block into itself");
  495.         return;
  496.     }
  497.     len = (blkend - blkbeg + 1) * wwd;
  498.     if ((hd = malloc(len)) == 0)
  499.         return;
  500.     cp1 = topptr + (blkbeg-1) * wwd;
  501.     movmem(cp1, hd, len);
  502.     cp2 = topptr + lineno(y) * wwd;
  503.     if (moving)    {
  504.         if (lineno(y) > blkbeg-1)
  505.             cp2 -= len;
  506.         do_display_text = 0;
  507.         delete_block();
  508.         do_display_text = 1;
  509.     }
  510.     if (cp2+len <= endptr)    {
  511.         movmem(cp2, cp2 + len, endptr - cp2 - len);
  512.         movmem(hd, cp2, len);
  513.     }
  514.     free(hd);
  515.     blkbeg = blkend = 0;
  516.     display_text();
  517. }
  518. /* ------------- copy a block ---------------- */
  519. static void copy_block(int y)
  520. {
  521.     mvblock(y, FALSE);
  522.     findlast();
  523. }
  524.  
  525. /* --------- move a block ------------ */
  526. static void move_block(int y)
  527. {
  528.     mvblock(y, TRUE);
  529. }
  530.  
  531. /* ------- find the last character in the buffer -------- */
  532. static void findlast()
  533. {
  534.     register char *lp = endptr - 1;
  535.     register char *tp = topptr;
  536.  
  537.     while (lp > tp && (*lp == ' ' || *lp == '\0'))    {
  538.         if (*lp == '\0')
  539.             *lp = ' ';
  540.         --lp;
  541.     }
  542.     if (*lp != ' ')
  543.         lp++;
  544.     lstptr = lp;
  545. }
  546.  
  547. /* ------- go to the end of the data in the buffer ------- */
  548. static void find_end(int *x, int *y)
  549. {
  550.     int ct;
  551.  
  552.     bfptr = lstptr;
  553.     ct = (lstptr - topptr) % wsz;
  554.     bfptr -= ct;
  555.     if (bfptr + wsz > endptr)
  556.         bfptr = endptr - wsz;
  557.     *y = (ct / wwd);
  558.     *x = 0;
  559.     downward(y);
  560. }
  561. /*page*/
  562. /* -------- carriage return -------- */
  563. static void carrtn(int *x, int *y, int insert)
  564. {
  565.     int insct;
  566.     char *cp, *nl;
  567.     int ctl = 2;
  568.  
  569.     cp = curr(*x, *y);
  570.     nl = cp + ((cp - topptr) % wwd);
  571.     if (lineno(*y) + 2 < lines)
  572.         if (insert && nl < endptr)    {
  573.             insct = wwd - *x;
  574.             while (ctl--)    {
  575.                 if (endptr > cp + insct)    {
  576.                     movmem(cp, cp+insct, endptr-insct-cp);
  577.                     setmem(cp, insct, ' ');
  578.                 }
  579.                 else if (ctl == 1)
  580.                     setmem(cp, endptr - cp, ' ');
  581.                 cp += insct * 2;
  582.                 insct = *x;
  583.             }
  584.         }
  585.     *x = 0;
  586.     downward(y);
  587.     if (insert)    {
  588.         test_para(*x, *y);
  589.         display_text();
  590.     }
  591.     if (lineno(*y) + 2 < lines)
  592.         if (insert)
  593.             if ((lstptr + wwd) <= endptr)
  594.                 if (lstptr > curr(*x, *y))
  595.                     lstptr += wwd;
  596. }
  597. /*page*/
  598. /* ------- move the buffer offset back one position ------ */
  599. static void backspace(int *x, int *y)
  600. {
  601.     if (*x == 0)    {
  602.         *x = wwd - 1;
  603.         upward(y);
  604.     }
  605.     else
  606.         --(*x);
  607. }
  608.  
  609. /* -------- move the buffer offset forward one word ------ */
  610. static void fore_word(int *x, int *y, char *bf)
  611. {
  612.     while (*bf != ' ')    {
  613.         if (spaceup(x, y, &bf) == 0)
  614.             return;
  615.         if (*x == 0)
  616.             break;
  617.     }
  618.     while (*bf == ' ')
  619.         if (spaceup(x, y, &bf) == 0)
  620.             return;
  621. }
  622.  
  623. static int spaceup(int *x, int *y, char **bf)
  624. {
  625.     if (*bf == lstptr)
  626.         return 0;
  627.     (*bf)++;
  628.     forward(x, y);
  629.     return 1;
  630. }
  631. /*page*/
  632. /* ------- move the buffer offset backward one word ------ */
  633. static void back_word(int *x, int *y, char *bf)
  634. {
  635.     spacedn(x, y, &bf);
  636.     while (*bf == ' ')
  637.         if (spacedn(x, y, &bf) == 0)
  638.             return;
  639.     while (*bf != ' ')    {
  640.         if (*x == 0)
  641.             return;
  642.         if (spacedn(x, y, &bf) == 0)
  643.             return;
  644.     }
  645.     spaceup(x, y, &bf);
  646. }
  647.  
  648. static int spacedn(int *x, int *y, char **bf)
  649. {
  650.     if (*bf == topptr)
  651.         return 0;
  652.     --(*bf);
  653.     backspace(x, y);
  654.     return 1;
  655. }
  656.  
  657.  
  658. /* ----- move the buffer offset forward one position ----- */
  659. static void forward(int *x, int *y)
  660. {
  661.     int ww = wwd;
  662.  
  663.     (*x)++;
  664.     if (*x == ww)    {
  665.         downward(y);
  666.         *x = 0;
  667.     }
  668. }
  669. /*page*/
  670. /* ------- move the buffer offset down one position ------ */
  671. static int downward(int *y)
  672. {
  673.     if (*y < wht - 1)    {
  674.         (*y)++;
  675.         return 1;
  676.     }
  677.     else if ((bfptr + wsz) < endptr)    {
  678.         bfptr += wwd;
  679.         scroll(wnd, UP);
  680.         disp_line(wht-1);
  681.         return 1;
  682.     }
  683.     return 0;
  684. }
  685.  
  686. /* -------- move the buffer offset up one position ------ */
  687. static void upward(int *y)
  688. {
  689.     if (*y)
  690.         --(*y);
  691.     else if ((topptr + wwd) <= bfptr)    {
  692.         bfptr -= wwd;
  693.         scroll(wnd, DN);
  694.         disp_line(0);
  695.     }
  696. }
  697.  
  698. /* ---- display all the lines in a window ------ */
  699. static void display_text()
  700. {
  701.     int y = 0;
  702.  
  703.     if (do_display_text)
  704.         while (y < wht)
  705.             disp_line(y++);
  706. }
  707. /*page*/
  708. /* ---------- Display a line -------- */
  709. static void disp_line(int y)
  710. {
  711.     int x = 0, atr = WNORMAL;
  712.  
  713.     if (blkbeg || blkend)
  714.         if (lineno(y) >= blkbeg-1)
  715.             if (lineno(y) <= blkend-1)
  716.                 atr = WACCENT;
  717.     while (x < wwd)    {
  718.         displ(wnd, x+1, y+1, *(bfptr+y * wwd+x), atr);
  719.         x++;
  720.     }
  721. }
  722.  
  723. /* ---------- set insert/exchange cursor shape ----------- */
  724. static void insert_line()
  725. {
  726.     set_cursor_type(inserting ? 0x0106 : 0x0607);
  727. }
  728.  
  729.